home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d18 / tphrt3.arc / WATCH.PAS < prev   
Pascal/Delphi Source File  |  1990-07-23  |  20KB  |  467 lines

  1. program watch;
  2. {----------------------------------------------------------------------------
  3.  |  Program WATCH.PAS                                                       |
  4.  |                                                                          |
  5.  |  This program creates a stopwatch on the display with "Taylor" split     |
  6.  |  capability.  It is meant to show how to use TPHRT with a hardware       |
  7.  |  interrupt in Turbo Pascal.                                              |
  8.  |                                                                          |
  9.  |  This program uses two timers to keep track of total and lap times.      |
  10.  |  This method can result in a least significant digit "jitter" of .01 sec |
  11.  |  on the lap timer.  A better, but more complex method is to use a single |
  12.  |  timer to keep track of both.  The dual timer method makes for better    |
  13.  |  demo code and was chosen for that reason only.                          |
  14.  |                                                                          |
  15.  |  This program uses BIOS interrupt F2h, which is unused in the current    |
  16.  |  interrupt map.  If a TSR program is using interrupt F2h, unpredictable  |
  17.  |  results will occur.  The original F2h interrupt vector is restored when |
  18.  |  the program completes.                                                  |
  19.  |                                                                          |
  20.  |  Environment: Turbo Pascal / Stack check OFF                             |
  21.  |                                                                          |
  22.  |  (c)1989 Ryle Design, P.O. Box 22, Mt. Pleasant, Michigan 48804          |
  23.  |                                                                          |
  24.  |  V3.00 Shareware Evaluation Version                                      |
  25.  ----------------------------------------------------------------------------}
  26.  
  27. {$S-}                                                   { stack check off }
  28.  
  29. uses
  30.     dos, crt, tphrt;
  31.  
  32. const
  33.     TIMEROFF  = 0;
  34.     TIMERON   = 1;
  35.     LAPSTOP   = 0;
  36.     LAPRUN    = 1;
  37.     F1        = 59;
  38.     F2        = 60;
  39.     KEYPORT   = $60;
  40.     OLD09V    = $F2;
  41.  
  42.     MSMINS    = 60000000;
  43.     MSSECS    = 1000000;
  44.     MSHUNDS   = 10000;
  45.  
  46. var
  47.     tstring   : string[8];
  48.     lstring   : string[8];
  49.  
  50.     atom      : char;
  51.  
  52.     tstate    : integer;
  53.     lstate    : integer;
  54.     laps      : integer;
  55.     cursor    : integer;
  56.  
  57.     ltime     : longint;
  58.     ttime     : longint;
  59.     hits      : longint;
  60.  
  61.     dtime     : array [1..2] of pchrt_type;
  62.  
  63.     old_keybd_int : pointer;
  64.     old_f2_int    : pointer;
  65.  
  66.  
  67.  
  68. function hide_cursor : integer;
  69. {---------------------------------------------------------------------------
  70.  |  This function disables the cursor.                                     |
  71.  |                                                                         |
  72.  |  Globals referenced: none                                               |
  73.  |                                                                         |
  74.  |  Arguments : void                                                       |
  75.  |                                                                         |
  76.  |  Returns   : (integer) cursor shape for later restoration               |
  77.  ---------------------------------------------------------------------------}
  78. var
  79.     regs        : registers;
  80.  
  81. begin
  82.     regs.ah := 15;                                              { get current video page }
  83.     intr($10,regs);
  84.  
  85.     regs.ah := 3;                                               { request cursor shape }
  86.     intr($10,regs);                                             { regs.bh has video page from last int86() call }
  87.  
  88.     hide_cursor := regs.cl + ( regs.ch shl 8);                  { store cursor start & stop rasters }
  89.  
  90.     regs.ah := 1;                                               { set cursor shape             }
  91.     regs.ch := 32;                                              { set bit 5 - turns cursor off }
  92.     intr($10,regs);                                             { and disable cursor           }
  93.  
  94. end; { hide_cursor }
  95.  
  96.  
  97.  
  98. procedure set_cursor(cursortype : integer);
  99. {----------------------------------------------------------------------------
  100.  |  This procedure sets the cursor to a new shape.                          |
  101.  |                                                                          |
  102.  |  Globals referenced: none                                                |
  103.  |                                                                          |
  104.  |  Arguments : (integer) cursortype - high 8 bits is start raster          |
  105.  |                                     low 8 bits is stop raster            |
  106.  |  Returns   : void                                                        |
  107.  ----------------------------------------------------------------------------}
  108. var
  109.     regs    : registers;
  110.  
  111. begin
  112.     regs.ah := 1;                                               { set cursor shape       }
  113.     regs.ch := (cursortype and $FF00) shr 8;                    { cursor start raster    }
  114.     regs.cl := (cursortype and $00FF);                          { cursor stop raster     }
  115.     intr($10,regs);                                             { call BIOS interupt 10h }
  116.  
  117. end; { set_cursor }
  118.  
  119.  
  120.  
  121. procedure new_keybd_int; interrupt;
  122. {----------------------------------------------------------------------------
  123.  |  This procedure is our new interrupt service routine for interrupt 9h.   |
  124.  |  The following occurs:                                                   |
  125.  |      1. The keyboard hardware port is read to see what key was pressed.  |
  126.  |      2. If F1 or F2 were pressed, the watch state is checked and         |
  127.  |         appropriate action is taken.                                     |
  128.  |      3. The old keyboard interrupt is called.                            |
  129.  |                                                                          |
  130.  |  Since this function is invoked by a hardware interrupt, it functions    |
  131.  |  asynchronously to the main program execution and provides extremely     |
  132.  |  high timing accuracy.                                                   |
  133.  |                                                                          |
  134.  |  Globals referenced: tstate                                              |
  135.  |                      lstate                                              |
  136.  |                      ltime                                               |
  137.  |                      ttime                                               |
  138.  |                      laps                                                |
  139.  |                      old_keybd_int                                       |
  140.  |                                                                          |
  141.  |  Arguments: void                                                         |
  142.  |                                                                          |
  143.  |  Returns  : void                                                         |
  144.  ----------------------------------------------------------------------------}
  145. var
  146.     scan_code   : byte;
  147.     regs        : registers;
  148.  
  149. begin
  150.     scan_code := port[KEYPORT];                     { read keyboard }
  151.     if (scan_code = F1) then                        { check for F1 key }
  152.     begin
  153.         if (tstate = TIMEROFF) then                 { if the watch is off ... }
  154.         begin
  155.             t_entry(1);                             { start main timer }
  156.             t_entry(2);                             { start lap timer  }
  157.             tstate := TIMERON;                      { set state flags  }
  158.             lstate := LAPRUN;
  159.         end
  160.         else                                        { the watch was on ... }
  161.         begin
  162.             t_exit(1);                              { stop main timer }
  163.             t_exit(2);                              { stop lap timer  }
  164.             tstate := TIMEROFF;                     { set flags       }
  165.             lstate := LAPSTOP;
  166.         end;
  167.     end
  168.     else if (scan_code = F2) then                   { check for F2 key }
  169.     begin
  170.         if (tstate = TIMEROFF) then                 { if watch was off }
  171.         begin
  172.             t_reset(1);                             { master reset     }
  173.             t_reset(2);
  174.             ttime := 0;
  175.             ltime := 0;
  176.             laps := 0;
  177.         end
  178.         else                                        { if watch was running }
  179.         begin
  180.             if (lstate = LAPRUN) then               { end of lap if lap was running }
  181.             begin
  182.                 t_exit(2);
  183.                 t_ask_timer(2,hits,ltime);
  184.                 t_reset(2);
  185.                 t_entry(2);
  186.                 lstate := LAPSTOP;
  187.                 laps := laps + 1;
  188.             end
  189.             else                                    { current lap continues if lap was off }
  190.             begin
  191.                 lstate := LAPRUN;
  192.             end;
  193.         end;
  194.     end;
  195.  
  196.     intr($F2,regs);                                 { call the old keyboard ISR }
  197.  
  198. end; { new_keybd_int }
  199.  
  200.  
  201.  
  202. procedure restore_old_keybd_int;
  203. {----------------------------------------------------------------------------
  204.  |  This procedure restores the original keyboard interrupt and must be     |
  205.  |  called prior to program completion.                                     |
  206.  |                                                                          |
  207.  |  Globals referenced: old_keybd_int                                       |
  208.  |                                                                          |
  209.  |  Arguments: void                                                         |
  210.  |                                                                          |
  211.  |  Returns  : void                                                         |
  212.  ----------------------------------------------------------------------------}
  213. begin
  214.     setintvec(9,old_keybd_int);                       { restore old ISR vectors }
  215.     setintvec($F2,old_f2_int);
  216.  
  217. end; { restore_old_keybd_int }
  218.  
  219.  
  220.  
  221. procedure install_new_keybd_int;
  222. {----------------------------------------------------------------------------
  223.  |  This procedure saves the original keyboard interrupt vector and installs|
  224.  |  the address of our user written interrupt handler in the ISR vector     |
  225.  |  table.                                                                  |
  226.  |                                                                          |
  227.  |  Globals referenced: old_keybd_int                                       |
  228.  |                      new_keybd_int                                       |
  229.  |                                                                          |
  230.  |  Arguments: void                                                         |
  231.  |                                                                          |
  232.  |  Returns  : void                                                         |
  233.  ----------------------------------------------------------------------------}
  234. begin
  235.     getintvec(9,old_keybd_int);                             { save old ISR vector    }
  236.     setintvec(9,addr(new_keybd_int));                       { install new ISR vector }
  237.  
  238.     getintvec($F2,old_f2_int);                              { save old ISR vector    }
  239.     setintvec($F2,old_keybd_int);                           { install new ISR vector }
  240.  
  241. end; { install_new_keybd_int }
  242.  
  243.  
  244.  
  245. procedure make_time_string(tval : longint; var tstring : string);
  246. {----------------------------------------------------------------------------
  247.  |  This procedure converts a quantity of microseconds into a displayable   |
  248.  |  string in the form MM:SS.HH .                                           |
  249.  |                                                                          |
  250.  |  Globals referenced: none                                                |
  251.  |                                                                          |
  252.  |  Arguments: (longint) tval - time in microseconds to convert             |
  253.  |             (string) tstring - string to receive time conversion         |
  254.  |                                                                          |
  255.  |  Returns  : void                                                         |
  256.  ----------------------------------------------------------------------------}
  257. var
  258.     mins, secs, hunds  : integer;
  259.     smins,ssecs,shunds : string[2];
  260.  
  261. begin
  262.     mins := tval div MSMINS;
  263.     tval := tval - (mins * MSMINS);
  264.  
  265.     secs := tval div MSSECS;
  266.     tval := tval - (secs * MSSECS);
  267.  
  268.     hunds := tval div MSHUNDS;
  269.  
  270.     str(mins,smins);                                    { mins to string }
  271.     if (length(smins) = 1) then smins := '0' + smins;
  272.  
  273.     str(secs,ssecs);                                    { secs to string }
  274.     if (length(ssecs) = 1) then ssecs := '0' + ssecs;
  275.  
  276.     str(hunds,shunds);                                  { hundreds to string }
  277.     if (length(shunds) = 1) then shunds := '0' + shunds;
  278.  
  279.     tstring := smins + ':' + ssecs + '.' + shunds;      { build final string }
  280.  
  281. end; { make_time_string }
  282.  
  283.  
  284.  
  285. procedure draw_watch;
  286. {----------------------------------------------------------------------------
  287.  |  This procedure draws the stopwatch on the display.                      |
  288.  |                                                                          |
  289.  |  Globals referenced: none                                                |
  290.  |                                                                          |
  291.  |  Arguments: void                                                         |
  292.  |                                                                          |
  293.  |  Returns  : void                                                         |
  294.  ----------------------------------------------------------------------------}
  295. var
  296.     indx    : integer;
  297.  
  298. begin
  299.     gotoxy(33,9);   write(chr(218));                     { draw the corners }
  300.     gotoxy(46,9);   write(chr(191));
  301.     gotoxy(33,15);  write(chr(192));
  302.     gotoxy(46,15);  write(chr(217));
  303.  
  304.     for indx :=34 to 45 do                              { draw horizontal lines }
  305.     begin
  306.         gotoxy(indx,9);   write(chr(196));
  307.         gotoxy(indx,15);  write(chr(196));
  308.         gotoxy(indx,12);  write(chr(196));
  309.     end;
  310.  
  311.     for indx :=10 to 14 do                              { draw vertical lines }
  312.     begin
  313.         gotoxy(33,indx);  write(chr(179));
  314.         gotoxy(46,indx);  write(chr(179));
  315.     end;
  316.  
  317.     gotoxy(33,12); write(chr(195));                      { draw vert/horiz intersections }
  318.     gotoxy(46,12); write(chr(180));
  319.  
  320.     gotoxy(35,10); write('Total Time');
  321.     gotoxy(37,13); write('Lap 00');
  322.  
  323. end; { draw_watch }
  324.  
  325.  
  326.  
  327. procedure show_total_time(ttime : longint);
  328. {----------------------------------------------------------------------------
  329.  |  This procedure displays the total time accumulated by the watch in the  |
  330.  |  appropriate area of the watch face.                                     |
  331.  |                                                                          |
  332.  |  Globals referenced: none                                                |
  333.  |                                                                          |
  334.  |  Arguments: (longint) ttime - time to display                            |
  335.  |                                                                          |
  336.  |  Returns  : void                                                         |
  337.  ----------------------------------------------------------------------------}
  338. var
  339.     tstring : string;
  340.  
  341. begin
  342.     make_time_string(ttime,tstring);    { convert microseconds to MM:SS.HH }
  343.  
  344.     gotoxy(36,11);  write(tstring);
  345.  
  346. end; { show_total_time }
  347.  
  348.  
  349.  
  350. procedure show_lap_time(ltime : longint);
  351. {----------------------------------------------------------------------------
  352.  |  This procedure displays the current lap time accumulated by the watch in|
  353.  |  the appropriate area of the watch face.                                 |
  354.  |                                                                          |
  355.  |  Globals referenced: none                                                |
  356.  |                                                                          |
  357.  |  Arguments: (longint) ltime - time to display                            |
  358.  |                                                                          |
  359.  |  Returns  : void                                                         |
  360.  ----------------------------------------------------------------------------}
  361. var
  362.     tstring : string;
  363.  
  364. begin
  365.     make_time_string(ltime,tstring);    { convert microseconds to MM:SS.HH }
  366.  
  367.     gotoxy(36,14);  write(tstring);
  368.  
  369. end; { show_lap_time }
  370.  
  371.  
  372.  
  373. procedure show_lap(lap : integer);
  374. {----------------------------------------------------------------------------
  375.  |  This procedure displays the current lap the watch is timing in the      |
  376.  |  appropriate area of the watch face.                                     |
  377.  |                                                                          |
  378.  |  Globals referenced: none                                                |
  379.  |                                                                          |
  380.  |  Arguments: (int) lap - lap to display                                   |
  381.  |                                                                          |
  382.  |  Returns: void                                                           |
  383.  ----------------------------------------------------------------------------}
  384. begin
  385.     if (lap = 100) then lap := 0;            { roll over after 99 laps }
  386.  
  387.     gotoxy(41,13);  write(lap:2);
  388.  
  389. end; { show_lap }
  390.  
  391.  
  392. begin
  393.  
  394.     { initialize things }
  395.  
  396.     t_start;
  397.  
  398.     ltime := 0;
  399.     ttime := 0;
  400.     laps  := 0;
  401.     tstate := TIMEROFF;
  402.     lstate := LAPSTOP;
  403.     atom := chr(0);
  404.  
  405.     { set up the display }
  406.  
  407.     clrscr;
  408.     cursor := hide_cursor;
  409.  
  410.     gotoxy(26,6); write('TPHRT Demonstration Series');
  411.     gotoxy(32,7); write('StopWatch V3.00');
  412.  
  413.     draw_watch;
  414.  
  415.     gotoxy(14,17); write('F1 Starts/Stops Watch          F2 Lap Splits/Resets Watch');
  416.     gotoxy(35,19); write('<ESC> quits');
  417.  
  418.     show_total_time(ttime);
  419.     show_lap_time(ltime);
  420.     show_lap(laps);
  421.  
  422.     install_new_keybd_int;
  423.  
  424.     { watch display update loop }
  425.  
  426.     repeat
  427.         if (tstate = TIMEROFF) then
  428.         begin
  429.             t_ask_timer(1,hits,ttime);
  430.             t_ask_timer(2,hits,ltime);
  431.             show_total_time(ttime);
  432.             show_lap_time(ltime);
  433.             show_lap(laps);
  434.         end
  435.         else
  436.         begin
  437.             t_get(dtime[1]);
  438.             ttime := t_diff(tdata[1]^.tstart,dtime[1]) + tdata[1]^.elapsed;
  439.             show_total_time(ttime);
  440.             if (lstate = LAPRUN) then
  441.             begin
  442.                 t_get(dtime[2]);
  443.                 ltime := t_diff(tdata[2]^.tstart,dtime[2]) + tdata[2]^.elapsed;
  444.                 show_lap_time(ltime);
  445.             end
  446.             else
  447.             begin
  448.                 show_lap_time(ltime);
  449.                 show_lap(laps);
  450.             end;
  451.         end;
  452.  
  453.         if keypressed then atom := readkey;
  454.  
  455.     until (atom = chr(27));
  456.  
  457.     { if user presses <ESC>, we fall through to here.  Clean up and exit }
  458.  
  459.     restore_old_keybd_int;
  460.  
  461.     set_cursor(cursor);
  462.     gotoxy(1,23);  writeln('StopWatch complete.');
  463.  
  464.     t_stop;
  465.  
  466. end.
  467.